﻿// -------------------------------------------------------------------------
//    @FileName         :    NFGMModule.cpp
//    @Author           :    Gao.Yi
//    @Date             :    2025-10-13
//    @Email			:    445267987@qq.com
//    @Module           :    NFGMModule
//    @Desc             :
//
// -------------------------------------------------------------------------

#include "NFGMModule.h"
#include "NFLogicConfig.h"
#include "NFPacketSendUtil.h"
#include "NFSession.h"
#include "NFPlayer.h"
#include "NFServiceGM.h"
#include "proto_cs_cmd.nanopb.h"

NFGMModule::NFGMModule(NFIPluginManager* p):NFLogicDynamicModule(p)
{

}

NFGMModule::~NFGMModule()
{
}

int NFGMModule::Awake()
{
    RegisterClientMessage(NF_ST_LOGIC_SERVER, E_CS_GM_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, E_CS_CHEAT_REPORT_REQ);

    RegisterAllCmd();
    return 0;
}

int NFGMModule::OnHandleClientMessage(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);
    if (!m_pObjPluginManager->IsInited(NF_ST_LOGIC_SERVER))
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server not inited, drop client msg:{}", packet.ToString());
        return -1;
    }

    if (m_pObjPluginManager->IsServerStopping())
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server is Stopping, drop client msg:{}", packet.ToString());
        return proto_ff::ERR_CODE_SERVER_IS_STOPPING;
    }

    int iRetCode = 0;
    switch (packet.nMsgId)
    {
        case proto_ff::E_CS_GM_REQ:
        {
            iRetCode = OnHandleGMReq(packet, pSession, req);
            break;
        }
        default:
        {
            iRetCode = -1;
            NFLogError(NF_LOG_DEFAULT, 0, "not handle msg:{}", packet.nMsgId);
        }
    }

    return iRetCode;
}

int NFGMModule::OnHandleGMReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);
    auto pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);
    if (NFLogicConfig::Instance()->IsGmClosed())
    {
        LOG_ERR(pPlayer->GetRoleID(), -1, "gm cmd closed");
        return ERR_CODE_NO_PRIVILEGES_OF_GM;
    }

    const proto_ff::Proto_CSGmReq* pCSGMReq = &(req.gm());
    CHECK_NULL(0, pCSGMReq);

    std::string gmContent = pCSGMReq->content();
    LOG_INFO(pPlayer->GetRoleID(), "gm cmd:{}", gmContent);

    std::vector<std::string> vecCmd;
    NFStringUtility::SplitString(gmContent, "\n", vecCmd);
    for (size_t i = 0; i < vecCmd.size(); i++)
    {
        int iRetCode = OnHandleOneGMReq(pPlayer, packet, vecCmd[i]);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "handle gm cmd:{}", gmContent);
    }
    return 0;
}

int NFGMModule::OnHandleOneGMReq(NFPlayer* pPlayer, NFDataPackage& packet, const std::string& cmd)
{
    CHECK_NULL(0, pPlayer);
    std::string content = cmd;
    NFStringUtility::Trim(content);
    NFStringUtility::ToLower(content);

    LOG_INFO(pPlayer->GetRoleID(), "begin handle gm content:{}", cmd);
    std::vector<std::string> vecCmd = NFStringUtility::SplitByRemoveSpace(content);

    if (vecCmd.size() <= 0)
    {
        std::string errCmd = NF_FORMAT("Parse Gm Cmd Failed:{}", cmd);
        NFPacketSendUtil::SendGMResToClient(pPlayer->GetClientSession(), 0, errCmd);
        LOG_ERR(pPlayer->GetRoleID(), -1, errCmd);
        return 0;
    }

    std::string cmdHead = vecCmd[0];
    std::vector<std::string> vecParams;
    if (vecCmd.size() > 1)
    {
       vecParams.assign(vecCmd.begin() + 1, vecCmd.end());
    }

    auto pCmdData = GetGMCmdData(cmdHead);
    if (pCmdData == nullptr || pCmdData->m_handler == nullptr)
    {
        std::string errCmd = NF_FORMAT("Gm Cmd Not Find:{}", cmdHead);
        NFPacketSendUtil::SendGMResToClient(pPlayer->GetClientSession(), 0, errCmd);
        LOG_ERR(pPlayer->GetRoleID(), -1, errCmd);
        return -1;
    }

    std::string info;
    int iRetCode = pCmdData->m_handler(pPlayer, packet, vecParams, info);
    if (iRetCode != 0)
    {
        std::string errCmd = NF_FORMAT("Gm Cmd Exec Error:{}, iRetCode:{} helpInfo:{} info:{}", cmd, iRetCode, pCmdData->m_helpInfo, info);
        NFPacketSendUtil::SendGMResToClient(pPlayer->GetClientSession(), 0, errCmd);
        LOG_ERR(pPlayer->GetRoleID(), -1, errCmd);
        return iRetCode;
    }
    NFPacketSendUtil::SendGMResToClient(pPlayer->GetClientSession(), 0, info);
    return 0;
}

NFGMCmdData* NFGMModule::GetGMCmdData(const std::string& cmd)
{
    std::string lowerCmd = NFStringUtility::ToLower(cmd);
    auto iter = m_gmCmdMap.find(lowerCmd);
    if (iter != m_gmCmdMap.end())
    {
        return &iter->second;
    }
    return nullptr;
}

int NFGMModule::RegisterCMCmd(const std::string& cmd, int perm, const std::string& helpInfo, NFGMCmdHandler handler)
{
    std::string lowerCmd = NFStringUtility::ToLower(cmd);
    NFGMCmdData *pCmdData = GetGMCmdData(lowerCmd);
    if (pCmdData)
    {
        LOG_ERR(0, -1, "cmd:{} has register, not repeated register", cmd);
        return -1;
    }

    pCmdData = &m_gmCmdMap[lowerCmd];
    pCmdData->m_cmd = lowerCmd;
    pCmdData->m_iPerm = perm;
    pCmdData->m_helpInfo = helpInfo;
    pCmdData->m_handler = handler;

    LOG_DEBUG(0, "RegisterCMCmd:{} perm:{} helpInfo:{}", lowerCmd, perm, helpInfo);
    return 0;
}

int NFGMModule::RegisterAllCmd()
{
    RegisterCMCmd("addlv", 1, "addlv #level", &NFServiceGM::AddLevel);
    RegisterCMCmd("additem", 1, "additem #id #num #bind", &NFServiceGM::AddItem);
    RegisterCMCmd("unittest", 1, "unittest", &NFServiceGM::UnitTest);
    RegisterCMCmd("clearbag", 1, "clearbag #bag", &NFServiceGM::ClearBag);
    RegisterCMCmd("arrangebag", 1, "arrangebag #bag", &NFServiceGM::ArrangeBag);
    RegisterCMCmd("savestorage", 1, "save to storage #bag #gridindex #num (#itemid #uuid)", &NFServiceGM::SaveStorage);
    RegisterCMCmd("pickstorage", 1, "pick form storage  #bag #gridindex #num #itemid #uuid", &NFServiceGM::PickStorage);
    RegisterCMCmd("buygrid", 1, "buy grid  #bag #times", &NFServiceGM::BuyGrid);
    return 0;
}
